package cn.edu.neu.vmmigeval.cloud.policy.impl;

import cn.edu.neu.vmmigeval.cloud.entity.Host;
import cn.edu.neu.vmmigeval.cloud.entity.Vm;
import cn.edu.neu.vmmigeval.cloud.policy.MigratedHostPolicy;
import cn.edu.neu.vmmigeval.cloud.policy.VmSelectionPolicy;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * The Minimum Utilization (MU) Broker selection policy.
 *
 * @author zzh
 */
public class VmSelectionPolicyMU extends VmSelectionPolicy {

    public VmSelectionPolicyMU() {

    }

    public VmSelectionPolicyMU(
            MigratedHostPolicy migratedHostPolicy) {
        super(migratedHostPolicy);
    }

    @Override
    public List<Vm> getMigratedVmsfromHost(Host host) {
        //System.out.println("查找节点"+host.getId()+"上Cpu上限触发需要迁移的虚拟机的集合");
        //得到当前host上的所有虚拟机

        List<Vm> vms = new ArrayList<Vm>();
        for (Vm vm : host.getVmList()) {
            if (!vm.isInMigration()) {
                vms.add(vm);
            }
        }

        ////////////////////////测试代码
        System.out.println("排序之前：  大小》" + vms.size());
        for (Vm vm : vms) {
            System.out.println("id:" + vm.getId() + "    cpu利用率：" + vm.getCurrentCpu() / vm.getTotalCpu());
        }
        //////////////////////////

        //对vm集合按照CPU利用率从高到低排序
        int size = vms.size();
        Vm vmJ = null;
        for (int i = 0; i < size; i++) {
            int maxIndex = i;
            Vm maxVm = vms.get(i);
            double maxRate = maxVm.getCurrentCpu() / maxVm.getTotalCpu();
            for (int j = i + 1; j <= size - 1; j++) {
                vmJ = vms.get(j);
                double rateJ = vmJ.getCurrentCpu() / vmJ.getTotalCpu();
                if (maxRate < rateJ) {
                    maxIndex = j;
                    maxRate = rateJ;
                }
            }
            if (maxIndex != i) {
                vmJ = vms.remove(maxIndex);
                vms.add(maxIndex, maxVm);
                vms.remove(i);
                vms.add(i, vmJ);
            }
        }

        ////////////////////////测试代码
        System.out.println("排序之后：  大小》" + vms.size());
        for (Vm vm : vms) {
            System.out.println("id:" + vm.getId() + "    cpu利用率：" + vm.getCurrentCpu() / vm.getTotalCpu());
        }
        //////////////////////////

        //计算最大内存占有率
        double maxRamRatio = 0.0;
        for (Vm vm : vms) {
            double ramRatio = vm.getCurrentRam() / host.getTotalRam();
            if (ramRatio > maxRamRatio) {
                maxRamRatio = ramRatio;
            }
        }


        int n = 2;  //要分段的区间数
        double sectionLength = maxRamRatio / n;  //每段的长度

        //将所有虚拟机加入分段集合
        List<List<Vm>> sections = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            sections.add(new ArrayList<>());
        }

        for (Vm vm : vms) {
            double ramRatio = vm.getCurrentRam() / host.getTotalRam();
            int temp = (int) (ramRatio / sectionLength);
            if (temp == n) {
                sections.get(temp - 1).add(vm);
            } else {
                sections.get(temp).add(vm);
            }
        }

        ////////////////////////测试代码
        System.out.println("分段之后：");
        for (int i = 0; i < n; i++) {
            System.out.println("##########第" + i + "段#########");
            ArrayList<Vm> lists = (ArrayList<Vm>) sections.get(i);
            for (Vm vm : lists) {
                System.out.println("id:" + vm.getId() + "    内存占有率：" + vm.getCurrentRam() / host.getTotalRam() + "    cup利用率：" + vm.getCurrentCpu() / vm.getTotalCpu());
            }
        }
        //////////////////////////

        //将利用率区间加入队列
        Queue<List<Vm>> q = new LinkedList<>();
        q.addAll(sections);

        List<Vm> destVms = new ArrayList<>();   //目标虚拟机集合
        int alpha = 2;  //需要迁移的样本数
        boolean flag = true;

        while (flag) {
            //判断队列Q是否为空
            if (!q.isEmpty()) {
                List<Vm> tempList = q.poll();
                int tempLength = tempList.size();

                //判断S中元素是否大于等于a
                if (tempLength >= alpha) {
                    for (int i = 0; i < alpha; i++) {
                        destVms.add(tempList.get(i));
                    }
                    flag = false;
                } else {
                    destVms.addAll(tempList);
                    alpha = alpha - tempLength;
                }
            } else {
                flag = false;
            }
        }

        System.out.println("目标迁移虚拟机个数为" + destVms.size() + ",如下：");
        for (Vm vm : destVms) {
            System.out.println("虚拟机" + vm.getId());
        }
        return destVms;
    }

    @Override
    public Vm getVmToMigrate(Host host) {

        return null;
    }

}
